package cn.security.config;

import cn.security.service.MySecurityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

//// 开启 Security ，
// 但是在 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration 中的
// org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration 类上
// 已经标注 @EnableWebSecurity
//@EnableWebSecurity
@Configuration
@Slf4j
public class MyConfig extends WebSecurityConfigurerAdapter {

    /**
     * 由于交给spring进行管理bean的生命周期，此处可以直接注入
     */
    @Autowired
    private MySecurityService mySecurityService;

    /**
     * 认证  AuthenticationManagerBuilder  配置
     * 如果 cn.security.service.MySecurityService 添加了  @Service 标记，此处注释或者放开都没问题
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info(" ******  configure  AuthenticationManagerBuilder  ********");
        // 基于内存配置
//        auth.inMemoryAuthentication()
//                .withUser("xiangjiao")
//                .password(passwordEncoder().encode("bunana"))
//                .authorities("admin")
//                .and()
//                .withUser("123")
//                .password(passwordEncoder().encode("123456"))
//                .authorities("role");

        // 基于   userDetailService
        // UserAuthenticationServiceImpl 实现  UserDetailsService，可以直接传递
        auth.userDetailsService(mySecurityService);
    }

    /**
     * 权限管理配置  HttpSecurity
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        log.info(" ******  configure  HttpSecurity  ********");
        http.formLogin() // 支持自定义登录界面跳转
                .loginPage("/login.html") // 登录页面设置
                .loginProcessingUrl("/user/login") // 登录请求接口设置，默认为  /login
                .defaultSuccessUrl("/test/index").permitAll() //登录成功之后，路径跳转
                .and()
                .authorizeRequests() // 校验请求
                .antMatchers("/","/test","/test/test4","/user/login").permitAll() // 设置哪些路径可以直接访问，不需要验证
                .anyRequest().authenticated()  // 所有请求都能访问
                .and()
                .csrf().disable(); // 关闭 csrf 防御


    }

    /**
     * 申明 {bcrypt} 对应的 BCryptPasswordEncoder 密码编码器 bean 对象；
     * 在进行 cn.security.service.UserServiceImpl#loadUserByUsername(java.lang.String) 时，注入使用
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}
